# -*- coding: utf-8 -*-
# created on 2016/12/22
from sympy import Eq, cancel, fraction, Poly, symbols, log, solve
from mathsolver.functions.base import BaseFunction, BasePoint, BaseFuncEq, new_latex
from mathsolver.functions.hanshu.base import is_fenshi001, is_logfenshi001
from mathsolver.functions.hanshu.duicheng import zhongxingduicheng_dingyishi
from mathsolver.functions.hanshu.helper import check_func
from mathsolver.functions.hanshu.hengchengli import fangcheng_hengchengli
from mathsolver.functions.hanshu.zhouqi import has_f
from mathsolver.functions.sympy_utils import get_all_child, default_symbol
from mathsolver.functions.hanshu.lianxu_qiuhe import HanShuLianXuQiuHe


def duicheng_axplubdivcxplusd(expr):
    """hs071.求函数y=(ax+b)/(cx+d)的对称中心，c != 0
    或者 log((ax+b)/(cx+d), m)"""
    if expr.has(log):
        args = expr.args
        if len(args) == 2:
            expr = args[1].args[0]
        else:
            expr = args[0]

    expr = cancel(expr)
    fenzhi, fenmu = fraction(expr)
    symbol = default_symbol(expr)
    c, d = Poly(fenmu, symbol).all_coeffs()
    if fenzhi.has(symbol):
        a, b = Poly(fenzhi, symbol).all_coeffs()
    else:
        a, b = 0, Poly(fenzhi, symbol).all_coeffs()
    res = (-d / c, a / c)
    step = "%s 的对称中心为 %s" % (new_latex(expr), res)
    return res, step


def she_duichengzhongxing(expr):
    """hs072.设出函数对称中心"""
    a, b = symbols('a, b')
    res = (a, b)
    step = "设 %s 的对称中心为 %s" % (expr, res)
    return res, step


class DuiChengZhongXing(BaseFunction):
    """求函数的对称中心"""

    def solver(self, *args):
        func = check_func(args[0])
        expr, var = func.expression, func.var

        # 类型二：求函数y=(ax+b)/(cx+d)的对称中心
        if is_fenshi001(expr, var) or is_logfenshi001(expr, var):
            res, step = duicheng_axplubdivcxplusd(expr)
            self.steps.append(["", step])
        # 类型三：求函数对称中心 - 定义式
        else:
            res_point, step1 = she_duichengzhongxing(expr)
            res_eq, step2 = zhongxingduicheng_dingyishi(res_point)
            eq = res_eq.lhs - res_eq.rhs

            fxs = set(get_all_child(eq, has_f))
            for fx in fxs:
                inner_f = fx.args[0]
                eq = eq.subs(fx, expr.subs(var, inner_f))
            # 方程恒成立得方程（组）
            ans_mapping, step3 = fangcheng_hengchengli(Eq(eq, 0))
            key, values = list(ans_mapping.items())[0]
            assert len(values) == 1
            dic = dict([(k, v) for k, v in zip(key, values.args[0])])
            res = tuple(dic.get(x) for x in res_point)
            step4 = "所以 %s 的对称中心为 %s" % (func.printing(), res)
            self.steps = [["", step1], ["", step2], ["", step3], ["", step4]]

        self.output.append(BasePoint({'name': '', 'value': res}))
        self.label.add("求函数的对称中心")
        return self


class DuiChengZhongXingQiuCan(BaseFunction):
    """已知函数y=(ax+b)/(cx+d)的对称中心求参数"""

    def solver(self, *args):
        func = check_func(args[0])
        expr, var = func.expression, func.var
        point = args[1].value

        # 求对称中心
        res, step = duicheng_axplubdivcxplusd(expr)
        self.steps.append(["", step])

        # 解方程组
        eqs = [expr1 - expr2 for expr1, expr2 in zip(res, point)]
        res = solve(eqs)
        if isinstance(res, list) and len(res) == 1:
            res = res[0]

        fmt = ', '.join('%s = 0' % eq for eq in eqs)
        self.steps.append(["所以 %s" % fmt, "解得 %s" % res])
        self.output.append(res)
        self.label.add("函数对称中心求参数")
        return self


class ZhongXingDuiChengQiuHe(BaseFunction):
    """函数中心对称求函数值的和"""

    def solver(self, *args):
        point = args[0].value
        poly = args[1]
        # 函数中心对称定义式
        eq, step = zhongxingduicheng_dingyishi(point)
        lianxuqiuhe_solver = HanShuLianXuQiuHe().solver(BaseFuncEq(eq.args), poly)

        self.steps.append(["", step])
        self.steps.extend(lianxuqiuhe_solver.steps)
        self.output = lianxuqiuhe_solver.output
        self.label.add("函数中心对称求函数值的和")
        return self


if __name__ == '__main__':
    pass
